#ifndef ABB_H
#define ABB_H

#include <stdbool.h>
#include <stddef.h>

/* ******************************************************************
 *                DEFINICION DE LOS TIPOS DE DATOS
 * *****************************************************************/

typedef struct abb abb_t;

typedef int (*abb_comparar_clave_t) (const char *, const char *);
typedef void (*abb_destruir_dato_t) (void *);

/* ******************************************************************
 *              PRIMITIVAS DEL ARBOL BINARIO DE BUSQUEDA
 * *****************************************************************/
 
// Crea un arbol binario.
// Post: devuelve un arbol binario vacio.
abb_t* abb_crear(abb_comparar_clave_t cmp, abb_destruir_dato_t destruir_dato);

// Guarda un elemento en el arbol binario.
// Pre: el arbol binario fue creado.
// Post: se agrego un nuevo elemento al arbol. La cantidad de elementos aumentó en uno.
bool abb_guardar(abb_t *arbol, const char *clave, void *dato);

// Borra un elemento del arbol binario.
// Pre: el arbol fue creado.
// Post: se elimina un elemento del arbol binario. La cantidad de elementos se reduce una unidad.
void *abb_borrar(abb_t *arbol, const char *clave);

// Devuelve el valor de un elemento en el arbol binario.
// Pre: el arbol binario fue creado.
void *abb_obtener(const abb_t *arbol, const char *clave);

// Devuelve true si el elemento pertenece al arbol, false en caso contrario.
// Pre: el arbol fue creado.
bool abb_pertenece(const abb_t *arbol, const char *clave);

// Devuelve la cantidad de elementos en el arbol binario. Si el arbol es NULL, devuelve -1.
// Pre: el arbol fue creado.
size_t abb_cantidad(abb_t *arbol);

// Destruye el arbol pasado por parametro.
// Pre: el arbol fue creado.
// Post: Se eliminan todos los elementos del arbol, y el arbol.
void abb_destruir(abb_t *arbol);

// Itera la funcion inorder aplicandole a cada elemento la funcion pasada por parametro.
// Pre: el arbol fue creado.
void abb_in_order(abb_t *arbol, bool funcion(const char *, void *, void *), void *extra);


/* ******************************************************************
 *              PRIMITIVAS DEL ITERADOR EXTERNO
 * *****************************************************************/

typedef struct abb_iter abb_iter_t;

// Crea un iterador de un arbol.
// Pre: el arbol pasado por parametro fue creado.
// Post: devuelve un iterador de un arbol.
abb_iter_t *abb_iter_in_crear(const abb_t *arbol);

// Avanza una posicion en el arbol. Se itera inorder.
// Pre: el iterador fue creado.
bool abb_iter_in_avanzar(abb_iter_t *iter);

// Devuelve la clave del nodo actual.
// Pre: el iterador fue creado.
const char *abb_iter_in_ver_actual(const abb_iter_t *iter);

// Devuelve true si el iterador se encuentra al final del arbol, false en caso contrario.
// Pre: el iterador fue creado.
bool abb_iter_in_al_final(const abb_iter_t *iter);

// Destruye un iterador.
// Pre: el iterador fue creado.
void abb_iter_in_destruir(abb_iter_t* iter);	

#endif //ABB_H
